import sys
import rclpy
from rclpy.node import Node
from base_interfaces_demo.msg import SensorData
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QVBoxLayout, 
                            QHBoxLayout, QGridLayout, QFrame)
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QSize
from PyQt5.QtGui import QFont, QColor
import pyqtgraph as pg
from collections import deque

# 数据可视化线程（处理ROS2通信）
class RosSubscriberThread(QThread):
    data_updated = pyqtSignal(float, float, float)  # (time, temp, humidity)

    def __init__(self):
        super().__init__()
        self.node = None
        self.subscription = None
        self.running = False

    def run(self):
        rclpy.init()
        self.node = Node("visualization_node")
        self.subscription = self.node.create_subscription(
            SensorData,
            '/sensor_data',
            self.sensor_callback,
            10
        )
        self.running = True
        while self.running:
            rclpy.spin_once(self.node, timeout_sec=0.1)

    def sensor_callback(self, msg):
        timestamp = self.node.get_clock().now().nanoseconds / 1e9  # 转换为秒
        self.data_updated.emit(timestamp, msg.temperature, msg.humidity)

    def stop(self):
        self.running = False
        if self.node:
            self.node.destroy_node()
        rclpy.shutdown()

# 主界面
class SensorDashboard(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.init_data()
        self.init_ros()

        # 设置窗口属性
        self.setWindowTitle('环境监测仪表盘')
        self.setMinimumSize(1000, 800)
        self.setStyleSheet("background-color: #F5F5F5;")

    def init_ui(self):
        # 创建主布局
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(20, 20, 20, 20)
        main_layout.setSpacing(0)

        # 标题
        title_label = QLabel("环境监测实时仪表盘")
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet("""
            QLabel {
                font: bold 28px '微软雅黑';
                color: #2C3E50;
                padding: 10px;
                border-bottom: 2px solid #3498DB;
            }
        """)
        main_layout.addWidget(title_label)

        # 实时数值卡片布局
        cards_layout = QHBoxLayout()
        cards_layout.setSpacing(0)

        # 温度卡片
        self.temp_card = self.create_card("#FF5722", "温度", "°C")
        cards_layout.addWidget(self.temp_card)

        # 湿度卡片
        self.humi_card = self.create_card("#2196F3", "湿度", "%")
        cards_layout.addWidget(self.humi_card)

        main_layout.addLayout(cards_layout)

        # 曲线图区域
        self.plot_widget = pg.GraphicsLayoutWidget()
        self.plot_widget.setBackground("#FFFFFF")
        
        # 温度曲线
        self.temp_plot = self.plot_widget.addPlot(title="温度变化趋势")
        self.temp_curve = self.temp_plot.plot(
            pen=pg.mkPen(color="#FF5722", width=3),
            shadowPen=pg.mkPen(color="#000000", width=3, alpha=0.2)
        )
        self.style_plot(self.temp_plot, "温度 (°C)")
        
        # 湿度曲线
        self.humi_plot = self.plot_widget.addPlot(title="湿度变化趋势")
        self.humi_curve = self.humi_plot.plot(
            pen=pg.mkPen(color="#2196F3", width=3),
            shadowPen=pg.mkPen(color="#000000", width=3, alpha=0.2)
        )
        self.style_plot(self.humi_plot, "湿度 (%)")

        main_layout.addWidget(self.plot_widget)
        self.setLayout(main_layout)

    def create_card(self, color, title, unit):
        card = QFrame()
        card.setMinimumSize(300, 150)
        card.setStyleSheet(f"""
            QFrame {{
                background-color: {color};
                border-radius: 15px;
                padding: 20px;
            }}
        """)

        layout = QVBoxLayout(card)
        
        # 标题
        title_label = QLabel(title)
        title_label.setStyleSheet("""
            QLabel {
                font: bold 20px '微软雅黑';
                color: white;
            }
        """)
        layout.addWidget(title_label)

        # 数值
        value_label = QLabel("--")
        value_label.setStyleSheet("""
            QLabel {
                font: bold 35px 'Arial';
                color: white;
                qproperty-alignment: 'AlignCenter';
            }
        """)
        layout.addWidget(value_label)

        # 单位
        unit_label = QLabel(unit)
        unit_label.setStyleSheet("""
            QLabel {
                font: 18px '微软雅黑';
                color: rgba(255, 255, 255, 150);
                qproperty-alignment: 'AlignRight';
            }
        """)
        layout.addWidget(unit_label)

        # 保存引用
        if title == "温度":
            self.temp_value = value_label
        else:
            self.humi_value = value_label

        return card

    def style_plot(self, plot, ylabel):
        plot.showGrid(x=True, y=True, alpha=0.3)
        plot.setLabel('left', ylabel, color="#666666", size=14)
        plot.setLabel('bottom', '时间', color="#666666", size=14)
        plot.getAxis("left").setPen(pg.mkPen(color="#666666"))
        plot.getAxis("bottom").setPen(pg.mkPen(color="#666666"))
        plot.setTitle(plot.titleLabel.text, color="#2C3E50", size="16pt")

    def init_data(self):
        self.max_length = 60
        self.time_data = deque(maxlen=self.max_length)
        self.temp_data = deque(maxlen=self.max_length)
        self.humi_data = deque(maxlen=self.max_length)

    def init_ros(self):
        self.ros_thread = RosSubscriberThread()
        self.ros_thread.data_updated.connect(self.update_data)
        self.ros_thread.start()

    def update_data(self, timestamp, temperature, humidity):
        # 更新卡片数值
        self.temp_value.setText(f"{temperature:.1f}")
        self.humi_value.setText(f"{humidity:.1f}")

        # 更新数据存储
        self.time_data.append(timestamp)
        self.temp_data.append(temperature)
        self.humi_data.append(humidity)

        # 更新曲线
        self.temp_curve.setData(list(self.time_data), list(self.temp_data))
        self.humi_curve.setData(list(self.time_data), list(self.humi_data))

    def closeEvent(self, event):
        self.ros_thread.stop()
        self.ros_thread.wait()
        super().closeEvent(event)

def main():
    app = QApplication(sys.argv)
    app.setFont(QFont("微软雅黑", 10))
    dashboard = SensorDashboard()
    dashboard.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()